package com.atguigu.tingshu.common.login;

import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.execption.GuiguException;
import com.atguigu.tingshu.common.result.ResultCodeEnum;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import jakarta.servlet.http.HttpServletRequest;
import lombok.Data;
import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.auth.AUTH;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Date;
import java.util.Map;

/**
 * ClassName: GuiGuLoginAspect
 * Package: com.atguigu.tingshu.common.aspect
 * Description:登录判断的切面类
 */
@Component
@Aspect
public class GuiGuLoginAspect{

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 校验用户是否登录,如果是登录状态,将用户信息存入本地线程
     * @param point
     * @return
     */
    @SneakyThrows
    @Around("@annotation(com.atguigu.tingshu.common.login.GuiGuLogin)")
    public Object a(ProceedingJoinPoint point){
        //初始化返回值
        Object result = null;
        //获取目标方法的参数
        Object[] args = point.getArgs();

        //获取请求对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
        //获取token
        String token = request.getHeader("token");
        //校验token是否为空
        if (StringUtils.isEmpty(token)){
            throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
        }

        try {
            //校验token是否合法,合法则获取用户id
            Long userId = Long.parseLong(
                    JwtHelper.decodeAndVerify(token, new RsaVerifier(SystemConstant.PUBLIC_KEY)).getClaims());
            //token合法,判断是否过期
            Map userInfoMap = (Map)redisTemplate.opsForValue().get("User:Login:" + userId);
            if (userInfoMap==null){
                //令牌过期重新发放令牌
                throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
            }
            //前端传的设备序列号
            String s = "设备序列号";
            //校验设备序列号,判断令牌是否被盗用
            if (!s.equals(userInfoMap.get("shebeixuleihao"))){
                throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
            }
            //登录将用户信息存入本地
            AuthContextHolder.setUserId(userId);
            AuthContextHolder.setVipExpireTime(((Date)userInfoMap.get("vipExpireTime")).getTime());
            AuthContextHolder.setIsVip(Integer.parseInt(userInfoMap.get("isVip").toString()));
            //登录则执行目标方法
            result = point.proceed(args);
            //返回
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            //token非法
            throw new GuiguException(ResultCodeEnum.LOGIN_AUTH);
        }finally {
            //清除空本地线程数据
            AuthContextHolder.removeUserId();
            AuthContextHolder.removeIsVip();
            AuthContextHolder.removeVipExpireTime();
        }
    }

}